<?php
namespace Zxf5115\Laravel\Kernel\Utils;

use ReflectionClass;
use RuntimeException;

/**
 * @author zhangxiaofei [<1326336909@qq.com>]
 * @dateTime 2025-09-12
 *
 * 反射工具类
 *
 * 提供基于命名约定的类解析功能，支持控制器到模型和服务类的自动映射
 */
class ReflectionUtil
{
  /**
   * 根据控制器类名解析对应的模型类
   *
   * @param string $controllerClass 完整的控制器类名（带命名空间）
   * @return string 解析后的模型类名
   */
  public static function resolveModelClass(string $controllerClass) : string
  {
    // 验证控制器类的有效性
    self::validateControllerClass($controllerClass);

    // 替换命名空间并移除控制器后缀
    $modelClass = str_replace(
        ['Http\\', 'Controllers', 'Controller'],
        ['', 'Models', ''],
        $controllerClass
    );

    // 验证类是否存在
    self::validateClassExists($modelClass, '模型');

    return $modelClass;
  }


  /**
   * 解析模型对应的Service类名
   * @param string $controllerClass 控制器类
   * @return string 服务类
   */
  public static function resolveServiceClass(string $controllerClass): string
  {
    // 验证控制器类的有效性
    self::validateControllerClass($controllerClass);

    // 获取当前控制器的反射对象
    $reflection = new ReflectionClass($controllerClass);

    // 提取控制器名称（移除Controller后缀）
    $baseName = rtrim($reflection->getShortName(), 'Controller');

    // 构建服务命名空间
    $serviceNamespace = str_replace(
      ['Http\\', 'Controllers'],
      ['', 'Services'],
      $reflection->getNamespaceName()
    );

    // 组装当前服务类名
    $serviceClass = $serviceNamespace . '\\' . $baseName . 'Service';

    // 验证类是否存在
    self::validateClassExists($serviceClass, '服务');

    return $serviceClass;
  }


  /**
   * 验证控制器类的有效性
   *
   * @param string $controllerClass
   */
  protected static function validateControllerClass(string $controllerClass) : void
  {
    if (!class_exists($controllerClass))
    {
      throw new InvalidArgumentException("控制器类 {$controllerClass} 不存在");
    }

    $reflection = new ReflectionClass($controllerClass);

    if(!str_ends_with($reflection->getShortName(), 'Controller'))
    {
      throw new InvalidArgumentException(
        "{$controllerClass} 不是有效的控制器类"
      );
    }
  }


  /**
   * 验证类是否存在
   *
   * @param string $className 类名
   * @param string $type 类类型描述（如"模型"、"服务"）
   */
  protected static function validateClassExists(string $className, string $type) : void
  {
    if(!class_exists($className))
    {
      throw new RuntimeException("{$type}类 {$className} 不存在，请检查命名约定");
    }
  }
}
